# Logistic Regression
# 两个罪犯活动的地理分类

import numpy as np
import matplotlib.pyplot as plt

from sklearn.metrics import confusion_matrix
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve,auc
from sklearn.metrics import classification_report

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负

# 数据准备 ########################################################################
x1 = np.random.normal([3, 2], [2, 2], [200, 2])   # 标签0数据
x2 = np.random.normal([7, 6], [2, 2], [200, 2])   # 标签1数据
xx = np.vstack((x1, x2))                      # 数据行堆叠
yy = np.asarray([0.] * len(x1) + [1.] * len(x2)) # 标签

plt.figure()  #绘制数据的分布
plt.scatter(x1[:, 0], x1[:, 1], label='0', c='r', marker='x')
plt.scatter(x2[:, 0], x2[:, 1], label='1', c='g', marker='1')


#划分训练集与测试集
x_train, x_test, y_train, y_test = train_test_split(xx, yy,
                                                    test_size=0.3,
                                                    random_state=2022)

## 模型建立 ########################################################################
model = LogisticRegression(penalty='l2', fit_intercept=True, verbose=0)
model.fit(x_train, y_train)
weight = model.coef_
bias = model.intercept_
print('权重：', weight, bias)
z = model.predict([[4, 5]])
print('预测：', z)

print('score', model.score(x_test, y_test))
#print(model.decision_function(x_test))
print('params', model.get_params(False))


##绘制两个类的散点图 ########################################################################
plt.figure()
ins = y_test == 0
xx_0 = x_test[ins, :]
xx_1 = x_test[~ins, :]
plt.scatter(xx_0[:, 0], xx_0[:, 1], label='0', c='r', marker='x')
plt.scatter(xx_1[:, 0], xx_1[:, 1], label='1', c='g', marker='1')


## 绘制边界 ########################################################################
def sigmoid(x):
    return 1. / (1. + np.exp(-x))
print(x_test.shape)

x1_boundary, x2_boundary = [], []
for xx1 in np.linspace(0, 10, 100):
    for xx2 in np.linspace(0, 10, 100):
        # z = sigmoid(xx1 * weight[0,0] + xx2 * weight[0,1] + bias)   #方法1：
        z = np.max(model.predict_proba([[xx1, xx2]]))     # 方法2： 这两个可以替换

        if abs(z - 0.5) < 0.01:
            x1_boundary.append(xx1)
            x2_boundary.append(xx2)
plt.scatter(x1_boundary, x2_boundary, c='b', marker='o', s=7)


## 画出ROC曲线 ########################################################################
y_pred = model.predict_proba(x_test)#每一类的概率
false_positive_rate, recall, thresholds = roc_curve(y_test, y_pred[:, 1])##得出roc绘图参数
roc_auc = auc(false_positive_rate,recall)#计算auc

print('roc:', roc_auc)

plt.figure()
plt.title('Receiver Operating Characteristic')
plt.plot(false_positive_rate, recall, 'b', label='AUC = %0.2f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([0.0,1.0])
plt.ylim([0.0,1.0])
plt.ylabel('Recall')
plt.xlabel('Fall-out')


# 计算混淆矩阵, 输出accuracy ########################################################################
# def model2(X):
#     return sigmoid( X @ weight.T + bias)
#
# y_pred = model2(x_test)
# mask = y_pred > 0.5
# y_test = y_test.reshape(-1, 1)
# ypred = np.zeros_like(y_test)
# ypred[mask] = 1      # 大于0.5的数值设为类别1

ypred = model.predict(x_test)  # 可以用predict 代替上面


print('混淆矩阵：', confusion_matrix(y_test, ypred))

report = classification_report(y_test, ypred)##
print('输出分类报告：', report)

# 单独输出 accuracy，precision，recall
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
print('accuracy:', accuracy_score(y_test, ypred))
print('precision:', precision_score(y_test, ypred, average='binary'))
print('recall:', recall_score(y_test, ypred, average='binary'))

plt.show()





